#include "ssd1306.h"
#include "i2c.h" // 根据实际I2C实现调整
#include "soc_osal.h"
#include "securec.h"
#include <string.h>

/* SSD1306 I2C地址 */
#define SSD1306_I2C_ADDR 0x3C

/* SSD1306命令集初始化 */
static const uint8_t ssd1306_init_cmds[] = {
    0xAE, // Display OFF
    0x20, 0x00, // Memory addressing mode: Horizontal
    0xB0, // Set page start address
    0xC8, // COM Output Scan Direction
    0x00, // Set low column address
    0x10, // Set high column address
    0x40, // Set display start line
    0x81, 0x7F, // Set contrast control
    0xA1, // Set segment re-map
    0xA6, // Normal display
    0xA8, 0x3F, // Set multiplex ratio
    0xA4, // Entire display ON
    0xD3, 0x00, // Set display offset
    0xD5, 0xF0, // Set display clock divide ratio/oscillator frequency
    0xD9, 0x22, // Set pre-charge period
    0xDA, 0x12, // Set COM pins hardware configuration
    0xDB, 0x20, // Set VCOMH deselect level
    0x8D, 0x14, // Enable charge pump regulator
    0xAF // Display ON
};

/* 内部缓冲区 */
static uint8_t SSD1306_Buffer[SSD1306_BUFFER_SIZE] = {0};

/**
 * @brief 重置OLED
 */
void ssd1306_Reset(void)
{
    // 根据实际硬件实现，可能涉及GPIO控制复位引脚
    osal_msleep(100);
}

/**
 * @brief 写命令
 */
void ssd1306_WriteCommand(uint8_t byte)
{
    uint8_t buffer[2] = {0x00, byte};
    i2c_write(SSD1306_I2C_ADDR, buffer, 2);
}

/**
 * @brief 写数据
 */
void ssd1306_WriteData(uint8_t *buffer, size_t buff_size)
{
    uint8_t *data = (uint8_t *)osal_vmalloc(buff_size + 1);
    if (data == NULL) {
        return;
    }
    data[0] = 0x40; // 数据标识符
    memcpy_s(&data[1], buff_size, buffer, buff_size);
    i2c_write(SSD1306_I2C_ADDR, data, buff_size + 1);
    osal_vfree(data);
}

/**
 * @brief 初始化OLED
 */
void ssd1306_Init(void)
{
    ssd1306_Reset();

    /* 初始化命令 */
    for (size_t i = 0; i < sizeof(ssd1306_init_cmds); i++) {
        ssd1306_WriteCommand(ssd1306_init_cmds[i]);
        osal_msleep(10);
    }

    ssd1306_Fill(Black);
    ssd1306_UpdateScreen();
}

/**
 * @brief 填充屏幕缓冲区
 */
void ssd1306_Fill(SSD1306_COLOR color)
{
    memset(SSD1306_Buffer, (color == White) ? 0xFF : 0x00, sizeof(SSD1306_Buffer));
}

/**
 * @brief 设置光标位置
 */
void ssd1306_SetCursor(uint8_t x, uint8_t y)
{
    g_ssd1306.CurrentX = x;
    g_ssd1306.CurrentY = y;
}

/**
 * @brief 更新屏幕显示
 */
void ssd1306_UpdateScreen(void)
{
    for (uint8_t page = 0; page < (SSD1306_HEIGHT / 8); page++) {
        ssd1306_WriteCommand(0xB0 + page); // 设置页地址
        ssd1306_WriteCommand(0x00); // 设置列低位
        ssd1306_WriteCommand(0x10); // 设置列高位
        ssd1306_WriteData(&SSD1306_Buffer[SSD1306_WIDTH * page / 8], SSD1306_WIDTH / 8);
    }
}

/**
 * @brief 绘制字符
 */
char ssd1306_DrawChar(char ch, FontDef Font, SSD1306_COLOR color)
{
    uint32_t i, b, j;

    if (g_ssd1306.CurrentX > (SSD1306_WIDTH - Font.FontWidth) ||
        g_ssd1306.CurrentY > (SSD1306_HEIGHT - Font.FontHeight)) {
        return 0;
    }

    for (i = 0; i < Font.FontHeight; i++) {
        b = Font.data[(ch - 32) * Font.FontHeight + i];
        for (j = 0; j < Font.FontWidth; j++) {
            if ((b << j) & 0x80) {
                ssd1306_DrawPixel(g_ssd1306.CurrentX + j, g_ssd1306.CurrentY + i, color);
            } else {
                ssd1306_DrawPixel(g_ssd1306.CurrentX + j, g_ssd1306.CurrentY + i, (SSD1306_COLOR)!color);
            }
        }
    }

    g_ssd1306.CurrentX += Font.FontWidth;

    return ch;
}

/**
 * @brief 绘制字符串
 */
char ssd1306_DrawString(char *str, FontDef Font, SSD1306_COLOR color)
{
    while (*str) {
        if (ssd1306_DrawChar(*str, Font, color) != *str) {
            return *str;
        }
        str++;
    }
    return *str;
}

/**
 * @brief 绘制单个像素
 */
void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color)
{
    if (x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT) {
        return;
    }

    if (color == White) {
        SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= (1 << (y % 8));
    } else {
        SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8));
    }
}

/* 其他绘图函数根据需要实现 */

